#!/usr/bin/python
# -*- coding: utf-8 -*-

#This file is part of pyLot library.
#
# pyLot is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyLot is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with pyLot.  If not, see <http://www.gnu.org/licenses/>.

__author__ = u'Pierre Puiseux, Guillaume Baty'
__copyright__ = u"Copyright 2011-2012 (C) andheo, Université de Pau et des Pays de l'Adour"
__credits__ = [u'Pierre Puiseux', u'Guillaume Baty']
__license__ = "GNU Lesser General Public License"

__all__ = [u"CommonRun"]
__date__ = u"9 févr. 2010"
__author__ = u"INRIA pyLot"

from traits.api import implements
from ..interfaces.i_commonrun import ICommonRun

from _pylot.minimal.path import  Path
from _pylot.minimal.utils import (Stopwatch, check_type)

class CommonRun (object):
  implements(ICommonRun)
  # /!\ This code may be useful : http://code.google.com/p/psutil/

  NotRunning = u'NotRunning' # Before start
  Running = u'Running' # Process in progress
  Finished = u'Finished' # Started and neither Paused nor Running
  Paused = u'Paused' # can be continued

  def __init__ (self, thread):
    u"""
    :param thread: run representation object 
    (threading.Thread, subprocess.Popen, PyQt4.QtCore.QProcess, 
    PyQt4.QtCore.QThread, ...)
    :type thread: variable 
    """
    object.__init__(self)
    self._state = self.NotRunning
    self._return_code = None
    self._working_directory = Path(u'.').abspath()
    self.exec_time = Stopwatch()
    self.start_time = None
    self.thread = thread

  def checkRunningState (self):
    if self.thread is None :
      return False
    else :
      if self.state == self.Running :
        return True
      else :
        return False

  def terminate (self):
    u"""
    terminate object
    """
    if self.checkRunningState() :
      self._terminate()

  def kill (self, signal=9):
    u"""
    kill object with signal
    """
    check_type(u'signal', signal, int)
    if self.checkRunningState():
      self._kill(signal)

  def getState (self):
    return self._getState()

  def getReturnCode (self):
    return_code = self._getReturnCode()
    check_type(u'return_code', return_code, int, none=True)
    return return_code

  # PLEASE IMPLEMENT THESES METHODS
  def _kill (self, signal):
    u"""
    here, process exists and is running or finished
    """
    raise NotImplementedError

  def _terminate (self):
    u"""
    here, process exists and is running or finished
    """
    raise NotImplementedError

  def _getState (self):
    raise NotImplementedError

  def _getReturnCode(self):
    raise NotImplementedError

  def _setWorkingDirectory (self, working_directory):
    self._working_directory = Path(working_directory).abspath()

  # Properties
  def _getstate (self):
    return self._getState()

  def _getreturn_code (self):
    return self._getReturnCode()

  def _setworking_directory (self, working_directory):
    check_type(u'working_directory', working_directory, [unicode, Path])
    return self._setWorkingDirectory(working_directory)

  state = property(fget=_getstate,
    doc=u'execution state: not running, running, finished')
  return_code = property(fget=_getreturn_code,
    doc=u'execution return code: 0: success, else: fail')
  working_directory = property(fget=lambda self: self._working_directory,
    fset=_setworking_directory,
    doc=u'execution directory. If not set, use current working directory')


if __name__ == '__main__':
  import doctest
  doctest.testmod()
